import bugtracking.Bug


import java.text.SimpleDateFormat
import bugtracking.History
import bugtracking.Actor
import bugtracking.ModificationEntry
import com.gargoylesoftware.htmlunit.HttpMethod
import java.util.concurrent.Semaphore
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.LinkedBlockingQueue;
/**
 * Created by IntelliJ IDEA.
 * User: AlexandruA
 * Date: 6/16/11
 * Time: 5:08 PM
 * To change this template use File | Settings | File Templates.
 */

//TODO use connection class
class BugzillaDriver implements Configuration {

    List list = null;

    public getIssuesUpdatedFrom = {Date startDate, Date endDate ->
        BugzillaConnection connection = BugzillaConnection.getInstance();
        list = [];//clear list necessary when called for more days
        String url = BUGZILLA_URL + BUG_LIST_PATH;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Map params = new HashMap();
//        params.put(END_DATE_PARAM, sdf.format(endDate));
//        params.put(START_DATE_PARAM, sdf.format(startDate));
        params.put(END_DATE_PARAM, "2011-11-22");
        params.put(START_DATE_PARAM, "2011-11-18");
        params.put(QUERY_PARAM, QUERY_PARAM_VALUE);
//        params.put("product", "Technical Support Issues");

        QueryString qs = new QueryString(params);
        def page = connection.createRequest(url, qs, HttpMethod.GET);

        def parser = new org.cyberneko.html.parsers.SAXParser();
        parser.setFeature('http://xml.org/sax/features/namespaces', false);
        def bugHTML = new XmlParser(parser).parseText(page.asXml());
        def showBugForm = null;
        showBugForm = bugHTML.'**'.FORM.find {it.@action ==  "show_bug.cgi"}
        String bugListAsString = "";
        if(showBugForm != null){
            showBugForm.INPUT.each {
                if(it.@name == "id"){
                    bugListAsString+=it.@value + ",";
                }
            }

//            bugListAsString = summarizeTimeForm.INPUT[0].@value
        } else {
            System.out.println("No bugs updated in specified period");
            return list;
        }
        url = BUGZILLA_URL + XML_PATH;
        params.clear();
        //TODO move hardcoded params to property file
        params.put("excludefield", "attachmentdata,long_desc");
        params.put("id", bugListAsString);
        params.put("ctype", "xml")
        qs.params.clear();
        qs.params = params;
        def xmlPage = connection.createRequest(url, qs, HttpMethod.POST);
        def xml = new XmlParser(parser).parseText(xmlPage.getContent())
        System.out.println(bugListAsString);
        def bugData
        xml.'**'.BUG.each {
            bugData = [bug_id: Integer.parseInt(it.BUG_ID.text().trim()),
                    creation_ts: sdf.parse(it.CREATION_TS.text().trim()),
                    delta_ts: sdf.parse(it.DELTA_TS.text().trim()),
                    short_desc: it.SHORT_DESC.text().trim(),
                    op_sys: it.OP_SYS.text().trim(),
                    priority: it.PRIORITY.text().trim(),
                    rep_platform: it.REP_PLATFORM.text().trim(),
                    bug_status: it.BUG_STATUS.text().trim(),
                    resolution: it.RESOLUTION.text().trim(),
                    severity: it.BUG_SEVERITY.text().trim(),
                    reporter: new bugtracking.Actor(name: it.REPORTER?.@name[0]?.trim(), email: it.REPORTER.text().trim()),
                    assigned_to: new bugtracking.Actor(name: it.ASSIGNED_TO?.@name[0]?.trim(), email: it.ASSIGNED_TO.text().trim()),
                    product: it.PRODUCT.text().trim(),
                    component: it.COMPONENT.text().trim(),
                    bug_version: it.VERSION.text().trim(),
                    target_milestone: it.TARGET_MILESTONE.text().trim(),
                    qa_contact: new bugtracking.Actor(email: it.QA_CONTACT?.text()?.trim(), name: it.QA_CONTACT?.@name[0]?.trim())
            ]
            list << new Bug(bugData);
        }
//        url = BUGZILLA_URL + BUG_ACTIVITY;
//        def semaphore = new Semaphore(0);
        def starttime = new Date();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 10,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
        list.each {Bug it ->
            threadPoolExecutor.execute(new HistoryInfoGetter(it))
        }
        println "shutdown"
        threadPoolExecutor.shutdown();
        threadPoolExecutor.awaitTermination(list.size()*10, TimeUnit.SECONDS);
        def endtime = new Date();

        println "end " + endtime
        println "nr of bugs " +list.size();
        println "total time " + (endtime.getTime()-starttime.getTime())
        return list;
    }



//    public void getHistoryInfo(Bug it, Semaphore semaphore){









//        def url = BUGZILLA_URL + BUG_ACTIVITY;
//        def parser = new org.cyberneko.html.parsers.SAXParser();
//        def run = new Runnable() {
//                void run() {
//                    try{
////  println "before" + it.bug_id;
//                        QueryString qs1 = new QueryString(["id": it.bug_id.toString()]);
//                        def page = BugzillaConnection.createRequest(url, qs1, HttpMethod.GET);
//    //                    println "after" + it.bug_id;
//                        def bugHTML = new XmlParser(parser).parseText(page.asXml());
//                        populateBugHistory(it, bugHTML);
//                    }catch(Exception e){
//                        println "exception: " + e
//                    }finally {
//                        semaphore.release();
//                    }
//                }
//            }
//            new Thread(run).start();

//    }

    public void populateBugHistory(Bug bug, def bugHTML) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
        History history = null;
        ModificationEntry modificationEntry = null;
        def bugzillaBody = bugHTML.'**'.DIV.find {it.@id == "bugzilla-body"};
        if (bugzillaBody.P[1].text().equals("No changes have been made to this bug yet.")) {
            return;
        }
        bugzillaBody.TABLE[0].TBODY[0].eachWithIndex {Node tr, int index ->
            if (index != 0) {
                if (tr.TD[0].@rowspan != null) {
                    modificationEntry = new ModificationEntry("modifiedProperty": tr.TD[2].text().trim(), "removedValue": tr.TD[3].text().trim(), "addedValue": tr.TD[4].text().trim());
                    history = new History("who": new Actor("email": tr.TD[0].text().trim()), "bug_when": sdf.parse(tr.TD[1].text().trim()));
                    history.entries = [modificationEntry];
                    if (bug.history == null) {
                        bug.history = [history];
                    } else {
                        bug.history.add(history)
                    }
                } else {
                    modificationEntry = new ModificationEntry("modifiedProperty": tr.TD[0].text().trim(), "removedValue": tr.TD[1].text().trim(), "addedValue": tr.TD[2].text().trim());
                    history.entries.add(modificationEntry);
                }
            }
        }
    }

//    private Map<String, String> getParamsForXML(String page) {
//        def bugHTML = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser()).parseText(page)
//        String bugListAsString = bugHTML.body.div.find {it.@id == "bugzilla-body"}.table.find {it.@class != "bz_buglist"}.tbody.tr.td[0].form[2].input[0].@value
//        Map map = new HashMap<String, Object>()
//
//        String excludedFields = "attachmentdata,long_desc"
//        map.put("id", bugListAsString)
//        map.put("excludefield", excludedFields)
//        map.put("ctype", "xml")
//        return map;
//    }
}


